package com.zhm.demo.modbus;

import com.ghgande.j2mod.modbus.Modbus;
import com.ghgande.j2mod.modbus.ModbusException;
import com.ghgande.j2mod.modbus.procimg.*;
import com.ghgande.j2mod.modbus.slave.ModbusSlave;
import com.ghgande.j2mod.modbus.slave.ModbusSlaveFactory;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;

@Slf4j
public class ModbusTCPServer {

    @Slf4j
    public static class ObservableProcessImage extends SimpleProcessImage {


        @Override
        public void setDigitalIn(int ref, DigitalIn value) throws IllegalAddressException {
            super.setDigitalIn(ref, value);
            log.info("Digital Out {} set to {}", ref, value);
        }

        @Override
        public void setRegister(int ref, Register register) throws IllegalAddressException {
            super.setRegister(ref, register);
            log.info("Register {} set to {}", ref, register.getValue());
        }

        @Override
        public void setInputRegister(int ref, InputRegister register) throws IllegalAddressException {
            super.setInputRegister(ref, register);
            log.info("Input Register {} set to {}", ref, register.getValue());
        }
    }

    public static void main(String[] args) {
        // 简单添加几个测试数据

        ObservableProcessImage spi = new ObservableProcessImage();


        // 添加输入寄存器（只读，用于传感器数据）
        spi.addInputRegister(199, new SimpleInputRegister(44));
        spi.addInputRegister(200, new SimpleInputRegister(462));

        // 添加数字量输出（线圈，可读写，用于控制设备）
        spi.addDigitalOut(11, new SimpleDigitalOut(true));
        spi.addDigitalOut(12, new SimpleDigitalOut(false));
        spi.addDigitalOut(13, new SimpleDigitalOut(true));
        spi.addDigitalOut(14, new SimpleDigitalOut(false));
        spi.addDigitalOut(15, new SimpleDigitalOut(true));
        spi.addDigitalOut(16, new SimpleDigitalOut(false));
        spi.addDigitalOut(17, new SimpleDigitalOut(true));
        spi.addDigitalOut(18, new SimpleDigitalOut(false));


        // 添加数字量输入（触点，只读，用于检测开关状态）
        spi.addDigitalIn(601, new SimpleDigitalIn(true));
        spi.addDigitalIn(602, new SimpleDigitalIn(true));
        spi.addDigitalIn(603, new SimpleDigitalIn(false));
        spi.addDigitalIn(604, new SimpleDigitalIn(true));
        spi.addDigitalIn(605, new SimpleDigitalIn(true));
        spi.addDigitalIn(606, new SimpleDigitalIn(true));
        spi.addDigitalIn(607, new SimpleDigitalIn(false));
        spi.addDigitalIn(608, new SimpleDigitalIn(true));


        spi.addRegister(800, new SimpleRegister(200));
        spi.addRegister(801, new SimpleRegister(99));



        // 端口
        int port = Modbus.DEFAULT_PORT;
        // 连接池大小(简单理解就是允许多少个主站同时连接)
        int poolSize = 2;
        // 从站Id
        int unitId = 1;

        try {
            ModbusSlave slave = ModbusSlaveFactory.createTCPSlave(port, poolSize);
            slave.addProcessImage(unitId, spi);
            // 多个从站就多个addProcessImage就可以了
            // 启动从站服务
            log.info("open server {}", port);
            slave.open();

            // 关闭(自定处理)
            //ModbusSlaveFactory.close();
        } catch (ModbusException e) {
            // 处理异常...
            //...
            throw new RuntimeException(e);
        }

    }
}

